package com.wl.dzt.sys.core.dao.curd;

import com.wl.dzt.sys.core.dao.mate.DataMateBase;
import com.wl.dzt.sys.core.dao.mate.DataMateColumn;
import com.wl.dzt.sys.core.dao.select.Select;
import com.wl.dzt.sys.util.CollectionUtil;
import com.wl.dzt.sys.util.FieldUtil;
import com.wl.dzt.sys.util.StringUtil;
import com.wl.dzt.sys.util.clazz.ClassUtil;
import org.springframework.cglib.beans.BeanMap;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * @author wl_code@163.com
 * @version 1.0
 * @date 2018/7/5/005
 * @description sql转换
 * 用于支持不同数据库操作的适配接口
 * 提供接口默认方法
 */
public interface CrudConvert {

    /**
     * <b>转换新增</b>
     * <p>
     * 用于转换为新增sql<br>
     * 该方法为接口默认方法,支持多数据库
     * </p>
     *
     * @param entity
     * @return·
     */
    // insert into %s (%s) values (%s)
    default CrudConvertResult insertConvert(Object entity) {
        BeanMap beanMap = BeanMap.create(entity);
        CrudConvertResult crudSqlResult = new CrudConvertResult();
        String tableName = DataMateBase.getTable(entity.getClass()).getTableName();
        List<String> fields = new ArrayList<>(), list = new ArrayList<>();
        List<Object> args = new ArrayList<>();
        beanMap.forEach((key, val) -> {
            DataMateColumn column = DataMateBase.getTable(entity.getClass()).getColumn(key.toString());
            if ("id".equals(key)) {
                val = (val == null || "".equals(val)) ? StringUtil.uuid() : val;
                beanMap.put("id", val);
                crudSqlResult.setId(val.toString());
            }
            if ("createDate".equalsIgnoreCase(key.toString())) {
                val = new Date();
            }
            if (val != null && column != null) {
                fields.add(column.getSqlName());
                list.add("?");
                args.add(ClassUtil.isBaseValType(val.getClass()) ? val : FieldUtil.doGetMethod(val, "id"));
            }
        });
        crudSqlResult.setArgs(args.toArray());
        crudSqlResult.setSql(String.format(CrudSql.INERT, tableName, CollectionUtil.join(fields, ","),
                CollectionUtil.join(list, ",")));
        return crudSqlResult;
    }

    /**
     * <b>转换修改</b>
     * <p>
     * 用于转换为修改sql<br>
     * 该方法为接口默认方法,支持多数据库
     * </p>
     *
     * @param entity
     * @return
     */
    // update %s set %s where id = %s
    default CrudConvertResult updateConvert(Object entity) {
        BeanMap beanMap = BeanMap.create(entity);
        String tableName = DataMateBase.getTable(entity.getClass()).getTableName();
        List<String> fields = new ArrayList<>();
        List<Object> args = new ArrayList<>();
        String id = beanMap.get("id").toString();
        beanMap.forEach((key, val) -> {
            DataMateColumn column = DataMateBase.getTable(entity.getClass()).getColumn(key.toString());
            if (!"id".equals(key) && val != null && column != null) {
                fields.add(column.getSqlName() + "=?");
                args.add(ClassUtil.isBaseValType(val.getClass()) ? val : FieldUtil.doGetMethod(val, "id"));
            }
        });
        args.add(id);
        CrudConvertResult crudSqlResult = new CrudConvertResult();
        crudSqlResult.setId(id);
        crudSqlResult.setArgs(args.toArray());
        crudSqlResult.setSql(String.format(CrudSql.UPDATE, tableName, CollectionUtil.join(fields, ",")));
        return crudSqlResult;
    }

    /**
     * <b>转换删除</b>
     * <p>
     * 用于转换为修删除sql<br>
     * 该方法为接口默认方法,支持多数据库
     * </p>
     *
     * @param clazz
     * @param id
     * @return
     */
    // delete from %s where id = ?
    default CrudConvertResult deleteConvert(Class<?> clazz, String id) {
        String tableName = DataMateBase.getTable(clazz).getTableName();
        CrudConvertResult crudSqlResult = new CrudConvertResult();
        crudSqlResult.setArgs(new Object[]{id});
        crudSqlResult.setSql(String.format(CrudSql.DELETE, tableName));
        return crudSqlResult;
    }

    /**
     * <b>转换查询</b>
     * <p>
     * 根据同数据库类型构建不同查询语句
     * </p>
     *
     * @param select
     * @return
     */
    CrudConvertResult selectConvert(Select select);

    /**
     * <b>转换总数查询</b>
     * <p>
     * 根据不同类型转换不同的总数查询语句
     * </p>
     *
     * @param select
     * @return
     */
    CrudConvertResult countConvert(Select select);

    /**
     * <b>获取分页sql模板</b>
     * <p>
     * 其中参数位置用%s表示
     * </p>
     *
     * @return
     */
    String getPageTemplate();
}
